在汽车电子软件开发领域摸爬滚打了十几年,我见证了行业的飞速发展与变革。从早期汽车电子系统的相对简单,到如今高度复杂且智能化的架构,AutoSAR(Automotive Open System Architecture)逐渐成为汽车软件设计的核心标准。
尤其是其中的应用层 APPL,它犹如汽车软件的灵魂,赋予了车辆各种智能功能。在实际项目中,无论是设计一款简单的车灯控制系统,还是复杂如 BMS 电池管理系统,APPL 的合理运用都起着决定性作用。
AppL中最重要的是SWC,而SWC与其他SWC通信需要接口, SWC中又由Runnable组成。
AppL主要的组成就分下面三部分:
应用软件组件(Application SWC)
AutoSAR接口(Ports)
可运行实体(Runnable)
先举个例子,如图所示为一个车灯控制系统的软件功能组件示意图
首先,我们需要明确系统中的几个关键部件,包括传感器(图中所示以及车门上的)、处理单元和执行器(这里指车顶灯)。参照上图所呈现的简单逻辑:系统中有左右两个车门,一个车灯,还有一个开关传感器。
在此系统中,图里呈现了 6 个软件组件(SWC),分别是 Right Door、Left Door、Door Contact、Switch、Dimmer 和 Light,对传感器、处理单元和执行器进行了划分,并且这些部件并非由一个电子控制单元(ECU)统一控制。这个例子值得大家记住,后续我们会基于这个例子逐步展开讲解。
SWC是最常见到的一个概念了。一般单独说的SWC指的是Atomic SWC。可以理解为应用层单元模块。
原子级 SWC 不可再拆分,对应一个为最小单元的.c 文件,其更小组成单元是可运行实体(runnable),若将 SWC 比作原子,runnable 就如同电子、质子和中子般与之密不可分,可把 SWC 视为最小单元,runnable 当作其中函数,且各 SWC 主要功能通常是实现特定算法。
有不可分割的SWC,就肯定有可分割的SWC。所以AutoSAR还规定了一类集合级的SWC,即 Composition SWC。就如同分子由众多原子组成一样,Composition SWC 可以拆分为一个个更小的 Atomic SWC。有些原子单独存在时没什么实际意义(当然也有像金、银、铜这类原子本身有实际意义的情况),而分子是具备实际意义的。
我们可以把功能相近或者为了方便查看整合到一处的 SWC(后续将 Atomic SWC 简称为 SWC)用一个 Composition SWC 包含起来,从功能角度来看,这样做有助于对 SWC 进行归类整理。
SWC 可形象地类比为.C 文件,而 Composition SWC 则是.C 文件的集合,在代码层面就相当于存放.C 文件的文件夹,这是 AutoSAR 所规定的集合级 SWC 的一种呈现形式。它具备分解为更小 Atomic SWC 的能力,常用于整合那些功能相近或者便于查看的 SWC,例如图中的 “灯光控制器组件” 就可当作 Composition SWC,把与之相关的如 Dimmer、Light 等 SWC 包含在内,使其成为自身的 Atomic SWC。
实际上,需要添加代码的不止是应用层的SWC。在BSW中,IO硬件抽象层(IoHwAb,和复杂驱动(Cdd)都是需要手动添加代码的,而这两个地方也可以算作是SWC,在DaVinci Developer中可以作为SWC进行配置和加runnable等操作的。因此,可将其看作是特殊的SWC。
虚拟功能总线(Virtual Function Bus)的结构,用于连接电子控制系统的各个组件,如开关、门、灯光等。通过这个总线,这些组件可以相互通信和协调工作,实现电子控制系统的智能化功能。这种基于虚拟总线的架构有利于系统的扩展性和灵活性,可以方便地添加或更换系统组件。
接口(Port)是依附在SWC上的概念,比如配置工具配置SWC后,需要配置这个SWC的Port。其实也好理解,如果一个C文件孤零零的放在那里,与别的C文件没有任何数据交互,那么作为一套代码中的一个C文件,根本没法发挥作用,所以必然在SWC上需要配置上或者输入(R-Port)的或者输出(P-Port)的Port。
软件组件的端口根据输入/输出方向可分为需型端口(Require Port,RPort)与供型端口(Provide Port,PPort),在AUTOSAR 4.1.1标准中又提出了供需端口(Provide and Require Port,PRPort)。需型端口可以和供型端口连接。
需型端口:用于从其他软件组件获得所需数据或所请求的操作;
供型端口:用于对外提供某种数据或某类操作;
供需端口:兼有需型端口与供型端口的特性。
AUTOSAR软件组件端口:
由于端口仅定义了方向,所以AUTOSAR中用端口接口(Port Interface)来表征端口的属性,端口接口类型主要有如下几种:
发送者-接收者接口(Sender-Receiver Interface, S/R);
客户端-服务器接口(Client-Server Interface,C/S);
模式转换接口(Mode Switch Interface);
非易失性数据接口(Non-volatile Data Interface);
参数接口(Parameter Interface);
触发接口(Trigger Interface);
最常用的端口接口是1、2。
如下图所示为AUTOSAR软件组件端口接口,软件组件SWC1具有2个端口:其中一个引用的端口接口类型为发送者-接收者(S/R)接口,另一个引用的端口接口类型为客户端-服务器(C/S)接口。对于引用发送者-接收者接口的一组端口而言,需型接口为接收者(Receiver),供型端口为发送者(Sender)。对于引用客户端-服务器接口的一组端口而言,需型端口为客户端(Client),供型端口为服务器(Server)。
实际上,在配置好的代码中,可以发现,如果我为SWC1和SWC2之间配置了一个SR的interface的话,SWC1中会有一个函数Rte_Write(),里面会对一个全局变量进行赋值。而另一边SWC2的里面会有一个Rte_Read()的函数,来读取这个全局变量。通过这种方式,达到了数据的交互。
Ports是SWC和SWC做接口(Interface)通信使用,或是SWC通过RTE和BSW做接口(Interface)通信使用,Ports主要分为5种类型。
发送者 - 接收者接口(SR_Interface)用于数据的传递关系,能实现发送者将数据发送给一个或多个接收者。在此类型接口中会定义一系列相互独立的数据元素(Data Elemet,DE),另外,一个软件组件的多个需型端口、供型端口、供需端口是可以引用同一个发送者 - 接收者接口的,而且它们能够使用该接口中所定义的任意一个或多个数据元素,并非一定要使用全部的数据元素。
一个接口可以包含多个数据,类似于通过结构体传输
可以传输基础数据类型(int,float等)和复杂数据类型(record,array等)
通信方式: 1:n 或者 n:1
如果一个data element要通过总线传输, 那么它必须与一个signal对应起来
通信方式 - 不使用队列
通信方式-使用队列
下图展示了一个典型的汽车电子系统中,通过发送-接收模式在不同硬件组件之间传输数据和信号的过程。
系统包含以下几个重要方面:
数据元素 (Data element):例如 Light_Dimm 代表亮度调节,DoorOpen 表示门开启,这些数据元素的数据类型丰富多样,涵盖整数、浮点数、数组以及记录等多种形式。
信号 (Signal):像 DoorLeft_Open 用于表示左车门开启的信号,其通信方式具备多样性,可实现 1:n 或者 n:1 的通信模式。
硬件组件:由 Roof ECU(车顶控制单元)、Microcontroller(微控制器)以及 AUTOSAR BSW(AUTOSAR 基础软件)等构成,它们是整个系统硬件层面不可或缺的部分。
通信机制:主要通过总线 (Bus) 来进行数据传输,并且运用映射 (mapping) 机制将数据元素与信号相互关联,以此保障系统内数据的准确传递与合理使用。
发送者 - 接收者接口的作用主要是传输数据,具体是通过 RTE(运行时环境)来传输数据,同时依靠 RTE 对数据传输进行管理,以此避免数据出现问题,比如防止出现同时调用同一数据时可能产生的错误情况。例如,Receiver 接口类型中就有 Rte_Read__() 这样与之相关的应用体现。
客户端 - 服务器接口用于操作(Operation,OP),体现的是一种函数调用关系,在这个关系中服务器作为操作的提供者,允许多个客户端调用同一个操作,但同一个客户端无法调用多个操作。该接口会定义一系列操作(也就是函数),这些操作由引用该接口的供型端口所在的软件组件来具体实现,进而提供给引用此接口的需型端口所在软件组件进行调用,
AUTOSAR 客户端 - 服务器端口具有以下几个主要特性:
提供 Operation 服务。
通信方式为 1:1 或 n:1(与发送者 - 接收者端口对应)。
支持同步或异步操作,同步调用相当于把函数直接插入上下文运行,而异步调用则需要等待,类似于让函数在另一个线程中运行,等运行完毕后再返回,原上下文依然可以继续运行。
一个接口可以提供多个操作,就是一个接口可以包含很多函数
ECU内部和跨ECU都可以调用,跨ECU也是通过外部总线
客户端-服务器端口定义:
在配置RTE的时候经常会出现这个词,在使用工具配置的时候,如果不太清楚Interface和Port等等的概念的话,即便机械的按照流程配置下来,也依旧不理解,甚至会导致换了一个配置工具后,因为不明白原理结果寸步难行。
通过我自己的配置经验,我觉得Interface是一个抽象的概念,是一个无法直接在代码中对应的概念。不像SWC可以比较准确的对应为C文件,Interface在配置工具的语境下包含了输入输出Port,以及两个Port之间的连接关系的一个集合。在工具中,会为一个Interface命名,再将输入输出Port连接到这个Interface上,这样RTE层内部如何实现两个Port之间的代码维度的连接,就是工具在生成的了,这个时候内部生成的不管是全局变量抑或是宏定义等等,都会基于这个Interface的元名称进行扩展。正因此,才会需要在工具层面上具象化Interface,并给他一个命名。
总的来讲,SR - Port(Sender - Reciever,发送者 - 接收者端口)主要承担着数据传输的功能。而 CS - Port(Client - Server,客户端 - 服务器端口)的作用则是调用另一个软件组件(SWC)中的服务,换个角度理解,其实就是调用另一个函数。落实到代码层面具体来看,SR - Port 的操作体现为对一个全局变量的操作,如果仅仅涉及 SWC 内部的数据传输,那么就会转变为对 Static 变量的操作了。而 CS - Port 的操作则表现为在一个函数中去调用另一个函数,尤其是当需要调用另一个 SWC 的函数时,就必须经过 RTE 来进行调用,这里所涉及的另一个 SWC,既可以位于本 ECU 内部,也可以处在跨 ECU 的位置,不过对于发起调用的 SWC 来说,是否跨 ECU 并没有实质性的区别。
在 AUTOSAR 中,运行实体(Runnable)是原子软件组件提供的最小代码段,也是可单独调度的任务,本质上是.c 文件内的函数。SWC 的运行需要通过 RTE 来调用 Runnable,且有 10ms、20ms、50ms 等不同的运行周期。
Runnables(即 Runnable entities)是 SWC 的组成部分,在 RTE 中运行,可由 RTE 的周期事件或其他事件触发调用,它包含了实际运行的函数。一个 SWC 可包含多个 Runnable Entity,如同一个 C 文件可包含多个函数,每个函数执行特定操作。并且 Runnable Entity 必须依附于 Task,就像函数只有被调用才能起作用,Runnable Entity 只有挂在 Task 上才能运行。
Runnable是主要用来封装SWC中的功能的。是由C语言函数实现的。一个SWC中需要至少要包含一个Runnable。简单举个例子:
Runnable 简单分为两类:
Category 1:No WaitPoint (在有限的时间内运行至结束,不能等待)。
Category 2:With a WaitPoint at least.(至少包含一个WaitPoint,运行过程中可以等待)
怎么在Runnable中设置WaitPoint?通过直接调用对应RTE API实现。
Rte_Receive() : 用于等待接收数据;
Rte_Feedback() : 用于等待数据发送完成;
Rte_Invalidate__(),表示sensor发送的数据无效,接收方feedback对无效值的处理
Rte_SwitchAck() : 用于等待模式切换操作;
Rte_Result() : 用于等待异步服务器调用的结果。
是操作系统(OS)管理的最小可调度单元。操作系统决定何时在ECU的CPU上运行哪个任务。在OS启动后,所有的Task都处于默认状态:挂起状态(Suspended)。Task被激活(Activated)后进入准备状态(Ready)。Ready的task将会按照优先级(Priority)的高低依次运行(Running)。
在RTE的代码中:
当TSK_Task1被激活并运行后,map到它的Runnable也会按map的顺序依次执行。
每个运行实体都会被赋予一个RTE事件(Trigger Event),即RTE 事件(RTE Event),这个事件可以引发这个运行实体的执行。
对于 RTE事件可以细分为很多种类,较常用的RTE事件有以下几种:
周期性(Periodic)事件,即Timing Event;
数据接收事件(Data-received Event);
客户端调用服务器事件(Server-call Event)。
在实际项目中,应用层主要由软件组件构成,这些组件各自承担特定的功能。
以BMS电池管理系统为例:BMS 中的软件组件如电压电流监测组件,它时刻与硬件传感器紧密协作,精准地采集电池组内各单体电池的电压与电流数据,像在纯电动汽车日常运行中,每隔极短时间就进行一次数据读取,这是后续诸多功能实现的基础。而 SOC 估算组件则凭借从监测组件获取的数据,运用专业算法去推算电池的荷电状态,准确的 SOC 数值能让驾驶员清晰知晓剩余续航里程,便于合理规划行程。热管理组件同样关键,它时刻关注电池温度,一旦在充放电时电池温度出现异常变化,像高温环境下,它便会迅速启动冷却风扇或者液冷系统来维持电池适宜的工作温度,避免电池性能下降甚至出现安全隐患。
这些软件组件之间通过端口和连接器来实现顺畅交互。电压电流监测组件的输出端口与 SOC 估算组件、热管理组件的输入端口相连接,好比搭建起了一座数据流通的桥梁,使得监测到的一手数据能及时传递给需要的组件进行后续处理,保障整个 BMS 系统有条不紊地运转。